package com.fub.positioning;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlSerializer;
import android.os.Environment;
import android.util.Log;
import android.util.Xml;

public class MeasurementsFilewriter {

	private static String ATTRIBUTE_SS = "ss";
	private static String ATTRIBUTE_SSID = "ssid";
	private static String TAG_NAME_AP = "ap";
	private static String TAG_NAME_ROOT = "root";
	private static String TAG_MEASUREMENT = "measurement";

	/**
	 * Returns a list of measurements from file
	 * 
	 * @param folder
	 *            the name of the folder
	 * @param filename
	 *            the name of the file
	 * @return
	 */
	public List<Measurement> loadMeasurements(String folder, String filename) {
		File rootFolder = new File(Environment.getExternalStorageDirectory(),
				folder);
		File file = new File(rootFolder, filename);
		Element root = getRootElement(file);
		NodeList measurementNodes = root.getElementsByTagName(TAG_MEASUREMENT);
		List<Measurement> loadedMeasurements = new ArrayList<Measurement>();
		for (int i = 0; i < measurementNodes.getLength(); i++) {
			Node measurementNode = measurementNodes.item(i);
			Measurement measurement = new Measurement();
			NodeList accessPoints = measurementNode.getChildNodes();
			for (int j = 0; j < accessPoints.getLength(); j++) {
				Node accessPoint = accessPoints.item(j);
				NamedNodeMap accessPointAttributes = accessPoint
						.getAttributes();
				if (accessPointAttributes == null)
					continue;
				String ssid = "noSSID";
				String ss = "-1";
				for (int k = 0; k < accessPointAttributes.getLength(); k++) {
					Node attribute = accessPointAttributes.item(k);
					if (attribute.getNodeName().equals(ATTRIBUTE_SSID)) {
						ssid = attribute.getNodeValue();
					}
					if (attribute.getNodeName().equals(ATTRIBUTE_SS)) {
						ss = attribute.getNodeValue();
						measurement.putSignalStrength(ssid,
								Integer.parseInt(ss));
					}
				}
			}
			loadedMeasurements.add(measurement);
		}
		return loadedMeasurements;
	}

	/**
	 * 
	 * Saves a list of measurements to file
	 * 
	 * @param measurements
	 *            the measurements
	 * @param folder
	 *            the name of the folder
	 * @param fileName
	 *            the name of the file
	 */
	public void saveMeasurements(List<Measurement> measurements, String folder,
			String fileName) {
		FileOutputStream fileos = createFile(fileName, folder);

		XmlSerializer serializer = Xml.newSerializer();
		try {
			serializer.setOutput(createFile(fileName, folder), "UTF-8");
			serializer.startDocument(null, Boolean.valueOf(true));
			serializer.setOutput(fileos, "UTF-8");
			serializer.startDocument(null, Boolean.valueOf(true));
			serializer.setFeature(
					"http://xmlpull.org/v1/doc/features.html#indent-output",
					true);
			serializer.startTag(null, TAG_NAME_ROOT);
			for (Measurement measurement : measurements) {
				serializer.startTag(null, TAG_MEASUREMENT);
				for (String ssid : measurement.getSSids()) {
					serializer.startTag(null, TAG_NAME_AP);
					serializer.attribute(null, ATTRIBUTE_SSID, ssid);
					serializer.attribute(null, ATTRIBUTE_SS,
							measurement.getSingnalStrength(ssid) + "");
					serializer.endTag(null, TAG_NAME_AP);
				}
				serializer.endTag(null, TAG_MEASUREMENT);
			}
			serializer.endTag(null, TAG_NAME_ROOT);
			serializer.endDocument();
			serializer.flush();
			fileos.close();
		} catch (Exception e) {
			Log.e("Exception", "error occurred while creating xml file");
		}
	}

	private Element getRootElement(File file) {
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document dom = builder.parse(file);
			Element root = dom.getDocumentElement();
			return root;
		} catch (Exception e) {
			throw new IllegalStateException("Document can't be parsed. ");
		}
	}

	private FileOutputStream createFile(String fileName, String folder) {
		File root = new File(Environment.getExternalStorageDirectory(), folder);
		if (!root.exists()) {
			root.mkdirs();
		}
		FileOutputStream fileos = null;
		try {
			fileos = new FileOutputStream(new File(root, fileName));
		} catch (FileNotFoundException e) {
			Log.e("FileNotFoundException", "can't create FileOutputStream");
		}
		return fileos;
	}
}
